package com.hc.sp06.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import sp01.util.JsonResult;

import javax.servlet.http.HttpServletRequest;

/**
 * 做一个权限过滤器  验证功能
 *
 * @author Z
 * @DATE 2021/8/31 17:06
 * @e-mail ...@qq.com
 */
//@Component
@Configuration
public class LoginFilter extends ZuulFilter {
    /**
     * pre 前置过滤器  里面有5个默认的过滤器，我们还可以添加自定义过滤器，
     *      自定义过滤器通过下面的方法设置位置.....
     *      默认的5个顺序不能改变，我们可以插入，但是没用
     * routing 路由过滤器    也可以是route 不知道为啥....
     * post 后置过滤器
     * error 错误过滤器   只在处理错误的时候使用
     */



//   过滤类型 返回的是一个过滤器类型
    @Override
    public String filterType() {
//        return "pre";     //可以这么写，也可以返回下面的常量...底层就是对应的字符串
        return FilterConstants.PRE_TYPE;
    }


//    位置顺序号
//    给大家再说一个小的知识点，如果咱们用的是前置过滤器（pre）。那么zuul在前置过滤器中放了一组默认的过滤器
//    这个方法可以指定你把你自定义的过滤器放在哪块。类似于数组下标
//    zuul的前置过滤器默认有5个，后边可以看一下这五个过滤器是什么
//     */
    @Override
    public int filterOrder() {
//  虽然理论上可以随便设置，但其实要设置在5个过滤器的后面，写在前面好像不执行.....
        return 6;
    }


//    判断 针对当前请求是否要执行过滤代码
    @Override
    public boolean shouldFilter() {
        /**
         * 这做一个功能代码的演示。需求
         * 调用商品服务item-service需要检查权限
         * 调用其他服务，不判断权限。可以直接访问
         *
         * 咱们有三个服务，那么你通过Zuul API网关去调用的时候
         * 你要调用商品，我去检查权限。
         * 你要调用用户和订单，我不去检查权限
         * 我们在这只做代码的演示，不去考虑这个业务是否合理
         */
        //1.获取当前请求调用的服务id
        //首先要得到服务的请求上下文对象(当前请求的上下文对象)
        RequestContext ctx= RequestContext.getCurrentContext();
        //拿到属性值,两种方式
//        ctx.get("serviceId");
        String serviceId=(String)ctx.get(FilterConstants.SERVICE_ID_KEY);
        //2.判断服务id是不是item-service
        //equalsIgnoreCase()，忽略大小写的比较方法
        //如果返回true，那么就需要执行下边的run方法
        return  "item-service".equalsIgnoreCase(serviceId);
    }

/*
    自定义过滤代码。
    在这编写你的过滤条件，他和shouldFilter()是绑定的
    因为有的请求是需要过滤权限的。
    有的请求不需要过滤权限。
    比如登录这个请求就需要过滤
    比如一个普通的商品列表，就不需要权限了。登录之后任何情况都能访问
    但是你访问订单的话，就必须有权限
*/
    @Override
    public Object run() throws ZuulException {
        //我们之前是不是在url中加了一个token
        //http://127.0.0.1:3001/item-service/ya13jifa?token=2yha123
        //咱们现在要获取这个token参数
        //获取token的话，要先得到request对象
        RequestContext ctx=RequestContext.getCurrentContext();
        HttpServletRequest request=ctx.getRequest();
        //用request接收token参数。咱们在请求路径中有可能得到null，或者是空串，或者是正常的值
        String token=request.getParameter("token");
        //如果收不到token，表示没登录过，阻止向后台服务转发，直接向客户端返回响应
        if(StringUtils.isEmpty(token)){
            //阻止向后台服务转发,
            ctx.setSendZuulResponse(false);
            //直接向客户端返回响应：JsonResult={code:400,msg:"not login!",data:null}
            //在06中加一个sp01依赖
            String json= JsonResult.err().code(JsonResult.NOT_LOGIN).msg("not login!").toString();
            //设置HTTP协议头属性：Content-Type:application/json;charset=UTF-8
            ctx.addZuulRequestHeader("Content-Type","application/json;charset=UTF-8");
            //json字符串作为响应体中的数据，发给客户端
            ctx.setResponseBody(json);
        }
        //在当前zuul版本中，没有使用这个返回值。
        // 虽然这个方法有一个object的返回值，
        //但是你返回任何东西都是无效的。
        //zuul的底层代码中并没有使用这个方法的返回值。所以你返回什么无所谓
        return null;
    }
}
